/**
 * *****************************************************************
 * @file    adt3102_spi.c
 * @author  WuHao(hwu@andartechs.com.cn)
 * @version 1.0.0
 * @date    2020-11-24
 * @brief   
 *                 Copyright (c) 2020, Andar Technologies Inc.
 *                           www.andartechs.com 
 *
 * *****************************************************************
 */
/*------------------------------ include -------------------------------------*/
#include "adt3102_type_define.h"
#include "gpio_ctype_map.h"
#include "spi_ctype_map.h"
#include "adt3102_spi.h"
#include "adt3102_gpio.h"
#include "adt3102.h"
#include "stdio.h"


/*------------------------------ function ------------------------------------*/
/**
 * @brief   spiInit.
 * @param   SpiX: SPI0/SPI1.
 * @param   spiMode: .
 * @return  None.
 * @note
 */
void spiInit(SPI_TypeDef *SpiX, uint8 spiMode)
{
    if (SpiX == SPI0)
    {
        GPIO->gpio_p03_config=1<<(0+spiMode)|1<<9|1<<10; //sclk  GPIO3
        GPIO->gpio_p04_config=1<<(0+spiMode)|1<<9|1<<10; //csn   GPIO4
        GPIO->gpio_p05_config=1<<(0+spiMode)|1<<9|1<<10; //miso  GPIO5
        GPIO->gpio_p06_config=1<<(0+spiMode)|1<<9|1<<10; //mosi  GPIO6
    }else{
        GPIO->gpio_p13_config=1<<(0+spiMode)|1<<9|1<<10; //sclk  GPI13
        GPIO->gpio_p14_config=1<<(0+spiMode)|1<<9|1<<10; //csn   GPI14
        GPIO->gpio_p15_config=1<<(0+spiMode)|1<<9|1<<10; //miso  GPI15
        GPIO->gpio_p16_config=1<<(0+spiMode)|1<<9|1<<10; //mosi  GPI16
    }
    SpiX->SSPCR0=0x07|0<<6|0<<7;
    SpiX->SSPCR1=0x04;
    SpiX->SSPCPSR=16;
    SpiX->SSPCR1=1<<1|spiMode<<2;
    SpiX->SSPIMSC=1<<1;
}


/**
 * @brief   manually set the cs signal of spi .
 *          spiCsSelect:high level     spiCsDeselect:low level
 * @param   SpiX: SPI0/SPI1.
 * @return  None.
 * @note
 */
void spiCsSelect(SPI_TypeDef *SpiX)
{
    gpioDirection(4, 0);
    if (SpiX == SPI0)
    {
        gpioOutput(4,1);
    }else{
        gpioOutput(14,1);
    }
}
void spiCsDeselect(SPI_TypeDef *SpiX)
{
    gpioDirection(4, 0);
    if (SpiX == SPI0)
    {
        gpioOutput(4,0);
    }else{
        gpioOutput(14,0);
    }
}


/**
 * @brief   spi write 1 byte data .
 * @param   SpiX: SPI0/SPI1.
 * @param   txData: tx data.
 * @return  None.
 * @note
 */
void spiWrite(SPI_TypeDef *SpiX,uint8 txData)
{  
    while((SpiX->SSPSR&0x02)!=0x02);
    while((SpiX->SSPSR&0x10)!=0x00);
    SpiX->SSPDR=txData;
    while((SpiX->SSPSR&0x04)!=0x04);
    while((SpiX->SSPSR&0x10)!=0x00);
}


/**
 * @brief   spi read 1 byte data .
 * @param   SpiX: SPI0/SPI1.
 * @return  None.
 * @note
 */
uint8 spiRead(SPI_TypeDef *SpiX)
{ 
//    while((SpiX->SSPSR&0x02)!=0x02);
//    while((SpiX->SSPSR&0x10)!=0x00);
//    SpiX->SSPDR=0xaa;
    while((SpiX->SSPSR&0x04)!=0x04);
    //while((SpiX->SSPSR&0x10)!=0x00);
    return SpiX->SSPDR;
}


/**
 * @brief   spi batch write data.
 * @param   SpiX: SPI0/SPI1.
 * @param   pbuf: wirte data buf.
 * @param   len: .
 * @return  None.
 * @note
 */
void spiWriteBurst(SPI_TypeDef *SpiX,uint8 *pbuf,uint16 len)
{
    volatile uint8 temp;
    uint16 j=0;
    for(int32 i=0;i<len-8;i=i+8)
    {
        while((SpiX->SSPSR&0x01)!=0x01);
        SpiX->SSPDR=pbuf[i];
        SpiX->SSPDR=pbuf[i+1];
        SpiX->SSPDR=pbuf[i+2];
        SpiX->SSPDR=pbuf[i+3];
        SpiX->SSPDR=pbuf[i+4];
        SpiX->SSPDR=pbuf[i+5];
        SpiX->SSPDR=pbuf[i+6];
        SpiX->SSPDR=pbuf[i+7];
        while((SpiX->SSPSR&0x08)!=0x08);
        temp = SpiX->SSPDR;
        temp = SpiX->SSPDR;
        temp = SpiX->SSPDR;
        temp = SpiX->SSPDR;
        temp = SpiX->SSPDR;
        temp = SpiX->SSPDR;
        temp = SpiX->SSPDR;
        temp = SpiX->SSPDR;
        j=j+8;
    }
    
    for(int32 k=j;k<len;k++)
    {
        while((SpiX->SSPSR&0x02)!=0x02);
        SpiX->SSPDR=pbuf[k];
        while((SpiX->SSPSR&0x04)!=0x04);
        temp = SpiX->SSPDR;
    }
}


/**
 * @brief   spi read burst.
 * @param   SpiX: SPI0/SPI1.
 * @param   pbuf: wirte data buf.
 * @param   len: .
 * @return  None.
 * @note
 */
void spiReadBurst(SPI_TypeDef *SpiX,uint8 *pbuf,uint16 len)
{
    volatile uint8 temp;
    uint16 j=0;
    for(int32 i=0;i<len-8;i=i+8)
    {
        while((SpiX->SSPSR&0x01)!=0x01);
        for (int32 p=0;p<8;p++)
        {
          SpiX->SSPDR=0xaa;
        }            
        while((SpiX->SSPSR&0x08)!=0x08);
        pbuf[i]   = SpiX->SSPDR;
        pbuf[i+1] = SpiX->SSPDR;
        pbuf[i+2] = SpiX->SSPDR;
        pbuf[i+3] = SpiX->SSPDR;
        pbuf[i+4] = SpiX->SSPDR;
        pbuf[i+5] = SpiX->SSPDR;
        pbuf[i+6] = SpiX->SSPDR;
        pbuf[i+7] = SpiX->SSPDR;
        j=j+8;
    }
    
    for(int32 k=j;k<len;k++)
    {
        while((SpiX->SSPSR&0x02)!=0x02);
        SpiX->SSPDR=0xaa;
        while((SpiX->SSPSR&0x04)!=0x04);
        pbuf[k] = SpiX->SSPDR;
    }
}


/**
 * @brief   SPI0 read write byte.
 * @param   SpiX: SPI0/SPI1.
 * @param   TxData: Need to send data.
 * @return  uint8.
 * @note
 */
uint8 spiReadWriteByte(SPI_TypeDef *SpiX,uint8 TxData)
{
    SpiX->SSPDR=TxData;
    while((SpiX->SSPSR&0x01)!=0x01){};
    while((SpiX->SSPSR&0x04)!=0x04){};
    return SpiX->SSPDR;
}


/**
 * @brief   Waiting for the SPI transmission status to become idle status.
 * @param   SpiX: SPI0/SPI1.
 * @return  None.
 * @note
 */
void Wait_bsy(SPI_TypeDef *SpiX)
{
  while((SpiX->SSPSR&0x10)==0x10);//bsyλ
}


/**
 * @brief   flashPd.
 * @param   SpiX: SPI0/SPI1.
 * @return  None.
 * @note
 */
void flashPd(SPI_TypeDef *SpiX)
{
    spiReadWriteByte(SpiX, 0xB9);
    Wait_bsy(SpiX);
}


/**
 * @brief   flash release pd.
 * @param   SpiX: SPI0/SPI1.
 * @return  None.
 * @note
 */
void flashReleasePd(SPI_TypeDef *SpiX)
{
    spiReadWriteByte(SpiX, 0xAB);
    Wait_bsy(SpiX);
}
